const draggable = {
  componentUpdated(el, { arg = false, value }) {
    const curDom = el; // 当前元素
    const parent = el.offsetParent; // 父级元素
    let flag = 1;
    curDom.style.cursor = '';
    const body = document.querySelector('body');
    if (arg) {
      curDom.style.cursor = 'move';
      let origin = {};
      curDom.onmousedown = (e) => {
        if (e.target !== curDom) return; // 当被点击的元素不是矩形框时，就阻止拖动
        // 鼠标按下，计算当前元素点击位置距离父级左上角的距离
        let disX = 0;
        let disY = 0;
        if (flag) { // 矩形框操作
          origin = {
            x: curDom.offsetLeft,
            y: curDom.offsetTop,
            w: parent.offsetWidth - curDom.offsetWidth, // 左右边界范围
            h: parent.offsetHeight - curDom.offsetHeight, // 上下边界范围
            viewX: parent.getBoundingClientRect().x, // 当前父级相对于视图区的x
            viewY: parent.getBoundingClientRect().y, // 当前父级相对于视图区的y
            width: curDom.offsetWidth,
            height: curDom.offsetHeight,
          };
          disX = e.clientX;
          disY = e.clientY;
          const { flag: tmpFlag, disX: tmpDisX, disY: tmpDisY } = downCode(curDom, disX, disY);
          flag = tmpFlag;
          disX = tmpDisX;
          disY = tmpDisY;
        }
        document.onmousemove = (e) => {
          e.preventDefault();
          body.style.userSelect = 'none';
          if (e.stopPropagation) {
            e.stopPropagation();
          } else {
            e.cancelBubble = true;
          }
          // 计算移动的距离 有value则是子元素，无value则为父元素
          if (flag === 2) {
            const { w: width, h: height } = moveCode(e, parent, flag, disX, disY, origin);
            curDom.style.width = width + 'px';
            curDom.style.height = height + 'px';
          } else if (flag === 1) {
            const { x: left, y: top } = moveCode(e, parent, flag, disX, disY, origin);
            curDom.style.left = left + 'px';
            curDom.style.top = top + 'px';
          }
          value && value(true); // 这里一般用不到，主要是判断当前dom是处于拖动状态还是未拖动状态
        };
        document.onmouseup = () => {
          document.onmousemove = null;
          document.onmouseup = null;
          body.style.userSelect = 'auto';
          value && value(false); // 这里一般用不到，主要是判断当前dom是处于拖动状态还是未拖动状态
        };
        document.onmouseleave = () => { // 当鼠标移动过快移出当前dom时，置空move事件
          if (flag !== 2) {
            document.onmousemove = null;
          }
        };
      };
    } else {
      curDom.onmousedown = null;
    }
  },
};
/**
 * 鼠标放下位置逻辑
 * @param {*} cur 当前节点
 * @param {*} x 点击x
 * @param {*} y 点击y
 * @returns
 */
const downCode = (cur, x, y) => {
  let disX = x - cur.getBoundingClientRect().x;
  let disY = y - cur.getBoundingClientRect().y;
  const difference = 8; // 当前矩形框的8px作为模糊拉伸范围
  let flag;
  const seX = (disX <= cur.offsetWidth && disX >= cur.offsetWidth - difference) || (disX > cur.offsetWidth && disX <= cur.offsetWidth + difference);
  const seY = (disY <= cur.offsetHeight && disY >= cur.offsetHeight - difference) || (disY > cur.offsetHeight && disY <= cur.offsetHeight + difference);
  // 目前只增加右下角拉伸
  if (seX && seY) {
    disX = 0;
    disY = 0;
    flag = 2;
    cur.style.cursor = 'crosshair';
  } else {
    flag = 1;
    cur.style.cursor = 'move';
  }
  return {
    disX: flag === 1 ? disX + cur.getBoundingClientRect().x : x,
    disY: flag === 1 ? disY + cur.getBoundingClientRect().y : y,
    flag,
  };
};
/**
 * 移动逻辑
 * @param {*} e 当前元素
 * @param {*} parent 父级元素
 * @param {*} flag 标志 0 => 父元素拖动， 1 => 子元素拖动, 2 => 子元素拉伸
 * @param {*} x0 原始坐标
 * @param {*} y0 原始坐标
 * @param {*} origin 原始位置
 * @returns 坐标xywh
 */
const moveCode = (e, parent, flag, x0, y0, origin) => {
  const x1 = e.clientX;
  const y1 = e.clientY;
  const startNew = {
    x: x0 - parent.getBoundingClientRect().x,
    y: y0 - parent.getBoundingClientRect().y,
    w: 0,
    h: 0,
  };
  if (flag === 1) {
    // 边界限制 将子元素限制在父元素内
    const left = x1 - x0 + origin.x;
    const top = y1 - y0 + origin.y;
    const leftRange = left > origin.w ? origin.w : left;
    startNew.x = left < 0 ? 0 : leftRange; // 左右边界限制
    const topRange = top > origin.h ? origin.h : top;
    startNew.y = top < 0 ? 0 : topRange; // 上下边界限制
  // 子元素拉伸放大缩小
  } else { // 拉伸边界范围限制，不能超过右下边界
    startNew.w = x1 - x0 + origin.width > parent.offsetWidth - origin.x ? parent.offsetWidth - origin.x : x1 - x0 + origin.width;
    startNew.h = y1 - y0 + origin.height > parent.offsetHeight - origin.y ? parent.offsetHeight - origin.y : y1 - y0 + origin.height;
  }
  return startNew;
};

export default draggable;
